#include "inet.h"

int serv_sock;
node_t *players;

extern uint8_t q_map[HEIGHT_AREA][WIDTH_AREA];

void connect_to_server(const struct sockaddr_in *addr, char *name) {
    mess_t message;

    printf("Connect to server %s ....\n", inet_ntoa(addr->sin_addr));

    serv_sock = Socket(AF_INET, SOCK_STREAM, 0);
    Connect(serv_sock, (struct sockaddr *)addr, sizeof(struct sockaddr_in));

    printf("Connect is established!\n");
    
    message.magic = htonl(MAGIC);
    message.ptype = htonl(0x01);
    message.datasize = htonl(strlen(name));

    Send(serv_sock, &message, sizeof(mess_t), 0);
    Send(serv_sock, name, ntohl(message.datasize), 0);
}


void get_map(uint8_t *q_map)
{
    mess_t message;
    
    Recv(serv_sock, &message, sizeof(mess_t), 0);
    
    message.magic = ntohl(message.magic);
    message.ptype = ntohl(message.ptype);
    message.datasize = ntohl(message.datasize);

    if (message.magic != MAGIC || message.ptype != 0x10)
        exit(__LINE__);

    Recv(serv_sock, q_map, message.datasize, 0);
}


void ready()
{
    mess_t message;

    message.magic = htonl(MAGIC);
    message.ptype = htonl(0x02);
    message.datasize = htonl(0x00);

    Send(serv_sock, &message, sizeof(mess_t), 0);
}


ex_player_t *start_game(char *cur_name, uint32_t *frame_delay, uint32_t *player_count)
{
    mess_t message;
    node_t *iter;

    ex_player_t *new_player;
    ex_player_t *cur_player;

    Recv(serv_sock, &message, sizeof(mess_t), 0);

    message.magic = ntohl(message.magic);
    message.ptype = ntohl(message.ptype);
    message.datasize = ntohl(message.datasize);

    if (message.magic != MAGIC || message.ptype != 0x20)
    {
        printf("[Pizda] Start game\n");
        exit(__LINE__);
    }

    Recv(serv_sock, frame_delay, sizeof(uint32_t), 0);
    Recv(serv_sock, player_count, sizeof(uint32_t), 0);

    *frame_delay = ntohl(*frame_delay);
    *player_count = ntohl(*player_count);

    init_list(&players);
    iter = players;
    for (int i = 0; i < *player_count && iter != NULL; ++i)
    {
        new_player = malloc(sizeof(ex_player_t));

        Recv(serv_sock, &new_player->pl.start_x, sizeof(uint32_t), 0);
        Recv(serv_sock, &new_player->pl.start_y, sizeof(uint32_t), 0);
        Recv(serv_sock, &new_player->pl.start_direction, sizeof(uint32_t), 0);
        Recv(serv_sock, &new_player->pl.player_name_len, sizeof(uint32_t), 0);

        new_player->pl.start_x = ntohl(new_player->pl.start_x);
        new_player->pl.start_y = ntohl(new_player->pl.start_y);
        new_player->pl.start_direction = ntohl(new_player->pl.start_direction);
        new_player->pl.player_name_len = ntohl(new_player->pl.player_name_len);

        Recv(serv_sock, new_player->pl.player_name, new_player->pl.player_name_len, 0);

        if (strcmp(cur_name, new_player->pl.player_name) == 0)
            cur_player = new_player;

        new_player->score = *player_count;
        iter = insert_node(iter, new_player);
    }

    return cur_player;
}


int get_state()
{
    mess_t message;
    node_t *iter;
    ex_player_t *pl;
    fd_set read_fd;

    struct timeval hui;

    uint8_t dir;
    char name[MAX_NAME_LEN + 1];

    FD_ZERO(&read_fd);
    FD_SET(serv_sock, &read_fd);

    hui.tv_sec = 0;
    hui.tv_usec = 0;
    select(serv_sock+1, &read_fd, NULL, NULL, &hui);

    if (!FD_ISSET(serv_sock, &read_fd))
        return 0;

    Recv(serv_sock, &message, sizeof(mess_t), 0);

    message.magic = ntohl(message.magic);
    message.ptype = ntohl(message.ptype);
    message.datasize = ntohl(message.datasize);

    if (message.magic != MAGIC || message.ptype != -1)
        return 0;

    Recv(serv_sock, &dir, 1, 0);
    Recv(serv_sock, name, message.datasize - 1, 0);
    
    if (dir != UP && dir != LEFT && dir != RIGHT && dir != DOWN)
        return 0;

    name[message.datasize - 1] = '\0';
    iter = players->next; 
    while (iter != NULL)
    {
        pl = (ex_player_t *)iter->data; 

        if (strcmp(pl->pl.player_name, name) == 0)
        {
            pl->pl.start_direction = dir;
            break;
        }
        
        iter = iter->next;
    }

    return 1;
}


void send_state(char *name, uint8_t dir)
{
    mess_t message;

    message.magic = htonl(MAGIC);
    message.ptype = htonl(0x00);
    message.datasize = htonl(1);

    Send(serv_sock, &message, sizeof(mess_t), 0);
    Send(serv_sock, &dir, 1, 0);
}
